package com.guigu.tms.dispatch.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.guigu.tms.commons.aggregation.entity.TransportLine;
import com.guigu.tms.commons.aggregation.feign.TransportLineFeignClient;
import com.guigu.tms.commons.dispatch.entity.CacheLine;
import com.guigu.tms.commons.dispatch.entity.CacheLineDetail;
import com.guigu.tms.commons.dispatch.entity.CacheLineUse;
import com.guigu.tms.commons.dispatch.entity.OrderClassify;
import com.guigu.tms.dispatch.dto.MachiningRoutePlanningDTO;
import com.guigu.tms.dispatch.dto.OrderLineDTO;
import com.guigu.tms.dispatch.dto.OrderLineSimpleDTO;
import com.guigu.tms.dispatch.dto.RoutePlanningDTO;
import com.guigu.tms.dispatch.service.ICacheLineDetailService;
import com.guigu.tms.dispatch.service.ICacheLineUseService;
import com.guigu.tms.dispatch.service.ITaskRoutePlanningService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class TaskRoutePlanningServiceImpl implements ITaskRoutePlanningService {

    @Autowired
    private TransportLineFeignClient transportLineFeignClient;

    @Autowired
    private ICacheLineUseService cacheLineUseService;

    @Autowired
    private ICacheLineDetailService cacheLineDetailService;

    @Override
    public List<OrderLineSimpleDTO>  execute(List<OrderClassify> orderClassifies, String agencyId, String jobId, String logId, String params) {

        //用于存放订单分类线路规划
        List<OrderLineDTO> orderLineDTOS=new ArrayList<>();

        orderClassifies.forEach(item->{
            if(item.isNew()){
                //查询当前机构所有线路
                RoutePlanningDTO routePlanningDTO = findLine(agencyId, item.getStartAgencyId(), item.getEndAgencyId(), new ArrayList<String>());
                //对查找到的线路加工、分析
                Map<CacheLine, List<CacheLineDetail>> cacheLineListMap = new MachiningRoutePlanningDTO(item.getStartAgencyId(), item.getEndAgencyId(), routePlanningDTO).get();

                //根据调度参数获取第一阶段路线
                CacheLineDetail defalutLine = findDefalutLine(cacheLineListMap, params);

                //线路关联订单分类
                relationOrder(defalutLine,item.getId());

                //返回线路信息
                orderLineDTOS.add(new OrderLineDTO(defalutLine, item));

            }else {
                // 根据订单分类编号查到之前的线路
                CacheLineDetail cacheLineDetail = findBeforeLine(item.getId(), agencyId);
                orderLineDTOS.add(new OrderLineDTO(cacheLineDetail, item));
            }
        });
        //构建精简订单分类模型
        List<OrderLineSimpleDTO> orderLineSimpleDTOS = buildOrderLineSimpleDTOS(orderLineDTOS);
        return orderLineSimpleDTOS;
    }

    /**
     * 构建精简订单分类模型
     * 根据不同线路的第一个中转点在此分配
     * 例：北京到上海  北京到深圳 两个种类订单，第一个中转点都会经过沿途的天津转运中心，那么这两个种类的订单就合成一类
     *
     * @param orderLineDTOS
     * @return
     */
    private List<OrderLineSimpleDTO> buildOrderLineSimpleDTOS(List<OrderLineDTO> orderLineDTOS) {
        Map<String, List<OrderClassify>> orderClassifyMap= new HashMap<>();
        Map<String, CacheLineDetail> cacheLineDetailMap = new HashMap<>();
        orderLineDTOS.forEach(orderLineDTO -> {
            //线路
            CacheLineDetail cacheLineDetail = orderLineDTO.getCacheLineDetail();
            //订单分类
            OrderClassify orderClassify = orderLineDTO.getOrderClassify();

            List<OrderClassify> orderClassifys = new ArrayList<>();
            //
            if (orderClassifyMap.containsKey(cacheLineDetail.getTransportLineId())) {
                orderClassifyMap.get(cacheLineDetail.getTransportLineId()).add(orderClassify);
            } else {
                orderClassifys.add(orderClassify);
                orderClassifyMap.put(cacheLineDetail.getTransportLineId(), orderClassifys);
            }
            cacheLineDetailMap.put(cacheLineDetail.getTransportLineId(), cacheLineDetail);

        });
        List<OrderLineSimpleDTO> orderLineSimpleDTOS = new ArrayList<>();
        cacheLineDetailMap.forEach((transportLineId, cacheLineDetail) -> {
            orderLineSimpleDTOS.add(new OrderLineSimpleDTO(cacheLineDetail, orderClassifyMap.get(transportLineId)));
        });
        return orderLineSimpleDTOS;
    }

    /**
     * 获取之前的路线
     * @param id
     * @param agencyId
     * @return
     */
    private CacheLineDetail findBeforeLine(String id, String agencyId) {

        //根据订单分类编号获得使用的线路
        QueryWrapper<CacheLineUse> wrapper=new QueryWrapper<>();
        wrapper.eq("order_classify_id", id);
        CacheLineUse  cacheLineUse= cacheLineUseService.getOne(wrapper);

        String cacheLineId=cacheLineUse.getCacheLineId();
        QueryWrapper<CacheLineDetail> wrapper1=new QueryWrapper<>();
        wrapper1.eq("cache_line_id",cacheLineId);
        wrapper1.eq("start_agency_id",agencyId );
        return cacheLineDetailService.getOne(wrapper1);
    }

    /**
     * 线路关联订单
     * @param defalutLine
     * @param id
     */
    private void relationOrder(CacheLineDetail defalutLine, String id) {
        CacheLineUse cacheLineUse = new CacheLineUse();
        cacheLineUse.setId(IdWorker.getIdStr());
        cacheLineUse.setOrderClassifyId(id);
        cacheLineUse.setCacheLineId(defalutLine.getCacheLineId());
        //保存
        cacheLineUseService.save(cacheLineUse);
    }

    /**
     * 根据调度参数获取对应路线
     * @param cacheLineListMap 可用线路
     * @param params 调度参数 1.距离最短 2.费用最少 3.时间最短 4.中转最少
     * @return
     */
    private CacheLineDetail findDefalutLine(Map<CacheLine, List<CacheLineDetail>> cacheLineListMap, String params) {
        if(cacheLineListMap.size()==0){
            return null;
        }
        //如果只有一条线路直接返回
        List<CacheLine> cacheLines=cacheLineListMap.keySet().stream().collect(Collectors.toList());
        if(cacheLines.size()==1){
            return cacheLineListMap.get(cacheLines.get(0)).get(0);
        }
        Integer p = Integer.valueOf(params);
        if(p==1){
            cacheLines.sort(Comparator.comparing(CacheLine::getDistance));
        }
        if(p==2){
            cacheLines.sort(Comparator.comparing(CacheLine::getCost));
        }
        if(p==3){
            cacheLines.sort(Comparator.comparing(CacheLine::getEstimatedTime));
        }
        if(p==4){
            cacheLines.sort(Comparator.comparing(CacheLine::getTransferCount));
        }
        return cacheLineListMap.get(cacheLines.get(0)).get(0);
    }

    /**
     * 查找线路
     * @param agencyId 机构编号
     * @param startAgencyId 起始机构编号
     * @param endAgencyId 目的机构编号
     * @return
     */
    public RoutePlanningDTO findLine(String agencyId, String startAgencyId, String endAgencyId,List<String> superiorIds){
        RoutePlanningDTO routePlanningDTO=new RoutePlanningDTO();
        //查询直达路线
        List<TransportLine> transportLine = findDirectLine(agencyId, startAgencyId, endAgencyId);
        if(!CollectionUtils.isEmpty(transportLine)){
            routePlanningDTO.setDirectTransportLine(transportLine);
        }
        //直达线路编号
        List<String> ids=transportLine.stream().map(item->item.getId()).collect(Collectors.toList());
        //查询起始机构路线
        transportLine=findStartLine(agencyId,startAgencyId);
        superiorIds.add(startAgencyId);
        //过滤直达线路和上级路线
        transportLine=transportLine.stream().filter(item->
             !ids.contains(item.getId())&&!superiorIds.contains(item.getEndAgencyId())
        ).collect(Collectors.toList());
        //如果起始机构可达其他机构的线路不为空，则继续查找
        if(!CollectionUtils.isEmpty(transportLine)){
            routePlanningDTO.setTransferTransportLine(transportLine);
            routePlanningDTO.setRoutePlanningDTOMap(new HashMap<>());
            for (TransportLine line : transportLine) {
                String startAgencyId1=line.getEndAgencyId();
                RoutePlanningDTO routePlanningDTO1=findLine(agencyId,startAgencyId1,endAgencyId,superiorIds);
                routePlanningDTO.getRoutePlanningDTOMap().put(line.getId(),routePlanningDTO1);
            }
        }
        return routePlanningDTO;
    }

    /**
     * 查询当前机构下的直达线路
     * @param agencyId
     * @param startAgencyId
     * @param endAgencyId
     */
    private List<TransportLine> findDirectLine(String agencyId, String startAgencyId, String endAgencyId) {
        TransportLine transportLine = new TransportLine();
        transportLine.setAgencyId(agencyId);
        transportLine.setStartAgencyId(startAgencyId);
        transportLine.setEndAgencyId(endAgencyId);
        transportLine.setStatus(1);
        //远程调用查询直达路线
       return transportLineFeignClient.getTransPortLine(transportLine);
    }

    /**
     * 获得起点线路
     * @param agencyId
     * @param startAgencyId
     * @return
     */
    public List<TransportLine> findStartLine(String agencyId,String startAgencyId){
        TransportLine transportLine = new TransportLine();
        transportLine.setAgencyId(agencyId);
        transportLine.setStartAgencyId(startAgencyId);
        transportLine.setStatus(1);
        return transportLineFeignClient.getTransPortLine(transportLine);
    }

}
